import { Effect } from 'dva';
import { Reducer } from 'redux';
import {
  getOrgData,
  getFirstLevelDepts
} from '@/services/design';
import {
  IOrgTreeItem,
  IResOrgTreeItem
} from '@/plugins/form/form-components/contract-select/ContactModal/interface';
import { SUCCESS_CODE } from '@/services/constant';

export interface IErrorField {
  name: string[];
  errors: string[];
  type?: string;
  visible?: boolean;
}

export interface IApplicantRange {
  relationId: string;
  relationType: number;
}
export interface IDetailBase {
  innerProcDefId: string;
  icon: string;
  procName: string;
  procRemark: string;
  procType: string;
  isPush: number;
  procKey: string;
  scopes?: IApplicantRange[];
  approvalAdmins?: string[];
}
export interface IDetailAdvance {
  repeatApproval: string;
  // selfProcAutoAgree: number[];
}

export interface IDetailForm {
  // formObj?: IGaeaAll;
  formId?: string;
}

// 后端返回 ----

export interface ResForm {
  id: string;
  formJson: string;
}

export interface IEditorDetail {
  base: IDetailBase;
  bpmXml: string;
  form: IDetailForm;
  // copyConditions?: ICopyCondition;
  advance: IDetailAdvance;
}

export interface IApprovalGroup {
  id: string;
  procTypeCode: string;
  procTypeName: string;
}

export interface DesignState {
  detail?: IEditorDetail;
  types?: Array<IApprovalGroup>;
  bpmErrors?: Array<IErrorField>;
  formErrors?: Array<IErrorField>;
  baseErrors?: Array<IErrorField>;
  orgData?: IOrgTreeItem[];
  flatternOrgData?: { [index: string]: IOrgTreeItem };
  // 流程挂载的时候触发出来供外面使用
  // bpmModeler?: Modeler;
}
export interface IDesignModel {
  namespace: 'design';
  state: DesignState;
  effects: {
    getOrgData: Effect;
    getFirstLevelDepts: Effect;
  };
  reducers: {
    saveOrgData: Reducer<DesignState>;
  };
}

const DesignModel: IDesignModel = {
  namespace: 'design',
  state: {
    detail: {} as IEditorDetail,
    types: []
  },
  effects: {
    * getFirstLevelDepts(_, { call }) {
      const response = yield call(getFirstLevelDepts) || {};
      return response;
    },
    * getOrgData(_, { call, put }) {
      const response = yield call(getOrgData) || {};
      const { status, data } = response;
      if (status == SUCCESS_CODE) {
        yield put({
          type: 'saveOrgData',
          payload: data
        });
      }
      return response;
    }
  },
  reducers: {
    saveOrgData(state, { payload }) {
      const formatTreeData = (
        treeData: IResOrgTreeItem[],
        parentKey?: string
      ) => {
        const result: IOrgTreeItem[] = [];
        let flattenObj: { [index: string]: IOrgTreeItem } = {};
        for (let i = 0; i < treeData.length; i++) {
          let formattedPersons: IOrgTreeItem[] = [];
          let children: IOrgTreeItem[] = [];
          const personFlattenObj: { [index: string]: IOrgTreeItem } = {};
          let childFlattenObj: { [index: string]: IOrgTreeItem } = {};

          if (treeData[i].persons) {
            formattedPersons = treeData[i].persons.map((el) => {
              const obj = {
                key: el.userId,
                title: el.name,
                type: el.type,
                icon: el.icon,
                parentKey: treeData[i].id
              };
              personFlattenObj[obj.key] = obj;
              return obj;
            });
          }
          if (treeData[i].children) {
            const tmp = formatTreeData(
              treeData[i].children || [],
              treeData[i].id
            );
            children = tmp.result;
            childFlattenObj = tmp.flattenObj;
            if (formattedPersons) {
              children = children
                ? children.concat(formattedPersons)
                : formattedPersons;

              childFlattenObj = { ...childFlattenObj, ...personFlattenObj };
            }
          }

          flattenObj = {
            [treeData[i].id]: {
              key: treeData[i].id,
              title: treeData[i].orgName,
              type: treeData[i].type,
              parentKey,
              icon: treeData[i].icon,
              children: children
            },
            ...flattenObj,
            ...childFlattenObj
          };
          result.push({
            key: treeData[i].id,
            title: treeData[i].orgName,
            type: treeData[i].type,
            children: children,
            icon: treeData[i].icon,
            parentKey: parentKey
          });
        }
        return { result, flattenObj };
      };
      const { result, flattenObj } = formatTreeData([payload]);
      return {
        ...state,
        orgData: result,
        flatternOrgData: flattenObj
      };
    }
  }
};

export default DesignModel;
